import datetime
import multiprocessing
import os
import re
import socket
import sys
import time
from functools import partial
from threading import Thread

import PySide6
from PySide6 import QtWidgets, QtCore
from PySide6.QtCore import QObject, Signal, QRegularExpression, QTimer
from PySide6.QtGui import Qt, QIcon, QRegularExpressionValidator
from PySide6.QtWidgets import QWidget, QGridLayout, QProgressBar, QLabel, QGroupBox, QPushButton, QCheckBox, QLineEdit, \
    QApplication, QFileDialog, QMessageBox

from extend_ui.err_log import log_decorator
from main_ui.dock_scope import AgeValidator
from main_ui.file_process import File_Process
import resources.resources_rc


class Program_Update(QWidget):
    def __init__(self, parent=None, config=None):
        super(Program_Update, self).__init__()
        # 获取变量
        self.config = config
        self.signal_operat = parent.signal_operat
        self.queue_logging = parent.queue_logging
        if config is None:
            self.config = {
                'file_path1': '',
                'file_path2': '',
                'IP': "192.168.1.11",
                'PORT': "1029",
                'check1': True,
                'check2': False
            }

        # 创建变量
        self.delay_time = 0.05      # 更新时手动增加的延时
        self.start_time = 0
        self.information = ''       # 要发送的版本信息
        self.old_version = ''       # 存储旧的版本信息

        self.get_update_MSG_timer = None

        # 创建用于弹窗的倒计时
        self.count_timer = QTimer()
        self.count_timer.timeout.connect(self.count_timer_slot)

        # self.queue_program_update = multiprocessing.Queue(maxsize=0)    # 用于更新远程升级的进度条
        #
        # self.get_update_MSG_timer = QtCore.QTimer()  # 保存config的定时器
        # self.get_update_MSG_timer.timeout.connect(self.get_update_MSG)
        # self.get_update_MSG_timer.start(5)


        self.initLayout()
        # self.get_e2prom_ver_time()
        self.add_info_data()
        self.show()

    def initLayout(self):
        """ 创建视图 """
        # 初始化窗口
        self.setWindowTitle('远程升级')
        # self.setFixedSize(500, 400)
        self.setMinimumHeight(400)
        self.setMinimumWidth(500)
        self.setWindowIcon(QIcon(':/logo.ico'))
        self.layout = QGridLayout(self)

        # 创建回显信号
        self.signal_echo = Singnal_Echo()
        self.signal_echo.echo_signal.connect(self.echo_text)

        # 创建完成信号
        self.signal_done = Singnal_Done()
        self.signal_done.done_signal.connect(self.update_done)

        # 进度条
        self.label_update = QLabel('更新进度')
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)

        # 显示进度
        self.label_text = QLabel('欢迎使用')
        self.label_text.setFixedHeight(15)

        # 布置三个窗口
        self.group_file = QGroupBox('文件配置')
        self.group_version = QGroupBox('版本信息')
        self.group_tcp = QGroupBox('网口烧写')
        self.group_btn = QGroupBox()
        self.layout_file = QGridLayout(self.group_file)
        self.layout_version = QGridLayout(self.group_version)
        self.layout_tcp = QGridLayout(self.group_tcp)
        self.layout_btn = QGridLayout(self.group_btn)


        # 开始按钮
        self.button_action = QPushButton('开始')
        self.button_action.setCheckable(True)
        self.button_Adaptive = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self.button_action.setSizePolicy(self.button_Adaptive)
        self.button_action.clicked.connect(self.update_tcp)
        self.layout_btn.addWidget(self.button_action, 1, 0, 1, 2)

        # 文件控件
        self.label_select = QLabel('选择')
        self.label_select.setFixedSize(30, 30)
        self.label_target = QLabel('目标位置')
        self.label_name = QLabel('文件名称')
        self.label_read = QLabel('读取按钮')

        self.check_filename1 = QCheckBox()
        self.label_filename1 = QLabel('CPU1文件')
        self.text_filename1 = QLineEdit()
        self.text_filename1.index = 0
        self.text_filename1.list_send = []
        self.text_filename1.list_line = []
        self.text_filename1.read_flag = False
        self.text_filename1.setReadOnly(True)
        self.text_filename1.check_flag = self.check_filename1
        self.button_loadfile1 = QPushButton('读取文件')
        self.button_loadfile1.clicked.connect(partial(self.select_file, self.text_filename1))

        self.check_filename2 = QCheckBox()
        self.label_filename2 = QLabel('CPU2文件')
        self.text_filename2 = QLineEdit()
        self.text_filename2.index = 1
        self.text_filename2.list_send = []
        self.text_filename2.list_line = []
        self.text_filename2.read_flag = False
        self.text_filename2.setReadOnly(True)
        self.text_filename2.check_flag = self.check_filename2
        self.button_loadfile2 = QPushButton('读取文件')
        self.button_loadfile2.clicked.connect(partial(self.select_file, self.text_filename2))

        # self.check_i10 = QCheckBox()
        # self.check_i10.stateChanged.connect(self.check_i10_slot)
        # self.label_i10 = QLabel('是否自动同步xxx.i10文件(CLA的数学库文件)')

        self.layout_file.addWidget(self.label_select, 0, 0, 1, 1, Qt.AlignHCenter)
        self.layout_file.addWidget(self.label_target, 0, 1, 1, 1, Qt.AlignHCenter)
        self.layout_file.addWidget(self.label_name, 0, 2, 1, 3, Qt.AlignHCenter)
        self.layout_file.addWidget(self.label_read, 0, 5, 1, 2, Qt.AlignHCenter)
        self.layout_file.addWidget(self.check_filename1, 1, 0, 1, 1, Qt.AlignHCenter)
        self.layout_file.addWidget(self.label_filename1, 1, 1, 1, 1)
        self.layout_file.addWidget(self.text_filename1, 1, 2, 1, 3)
        self.layout_file.addWidget(self.button_loadfile1, 1, 5, 1, 2)
        self.layout_file.addWidget(self.check_filename2, 2, 0, 1, 1, Qt.AlignHCenter)
        self.layout_file.addWidget(self.label_filename2, 2, 1, 1, 1)
        self.layout_file.addWidget(self.text_filename2, 2, 2, 1, 3)
        self.layout_file.addWidget(self.button_loadfile2, 2, 5, 1, 2)
        # self.layout_file.addWidget(self.check_i10, 3, 0, 1, 1, Qt.AlignHCenter)
        # self.layout_file.addWidget(self.label_i10, 3, 1, 1, 6)

        # 网口控件
        self.label_IP = QLabel('IP地址:')
        self.label_PORT = QLabel('端口号:')
        self.text_IP = QLineEdit()
        self.text_IP.setInputMask('000.000.000.000')
        self.text_PORT = QLineEdit()
        self.text_PORT.setValidator(AgeValidator(65535))
        self.layout_tcp.addWidget(self.label_IP, 0, 0, 1, 1)
        self.layout_tcp.addWidget(self.label_PORT, 1, 0, 1, 1)
        self.layout_tcp.addWidget(self.text_IP, 0, 1, 1, 1)
        self.layout_tcp.addWidget(self.text_PORT, 1, 1, 1, 1)

        # 版本号
        self.label_ver = QLabel('版本号:')
        self.label_ver.setFixedWidth(60)
        self.label_time = QLabel('未获取到!')
        self.label_time.setAlignment(Qt.AlignCenter)
        self.label_time.setFixedWidth(120)
        self.text_ver = QLineEdit()
        self.text_ver.setEnabled(False)
        # self.text_ver.setInputMask('000.000.000')
        reg = QRegularExpression("^(\\d{1,3}\\.){0,2}\\d{1,3}$")
        validator = QRegularExpressionValidator(self)
        validator.setRegularExpression(reg)
        self.text_ver.setValidator(validator)
        self.text_ver.setAlignment(Qt.AlignCenter)
        self.text_ver.setFixedWidth(120)
        self.check_ver = QCheckBox('更新版本号')
        self.check_ver.stateChanged.connect(self.check_ver_change_slot)
        self.layout_version.addWidget(self.label_ver, 0, 0, 1, 1)
        self.layout_version.addWidget(self.label_time, 0, 1, 1, 1, Qt.AlignHCenter)
        self.layout_version.addWidget(self.text_ver, 0, 2, 1, 1, Qt.AlignHCenter)
        self.layout_version.addWidget(self.check_ver, 0, 3, 1, 1, Qt.AlignHCenter)

        self.layout.addWidget(self.label_update, 0, 0, 1, 1)
        self.layout.addWidget(self.progress_bar, 0, 1, 1, 9)
        self.layout.addWidget(self.label_text, 1, 1, 1, 9)
        self.layout.addWidget(self.group_file, 2, 0, 3, 10)
        self.layout.addWidget(self.group_version, 5, 0, 1, 10)
        self.layout.addWidget(self.group_tcp, 6, 0, 2, 6)
        self.layout.addWidget(self.group_btn, 6, 6, 2, 4)

    def check_ver_change_slot(self):
        if self.check_ver.isChecked():
            self.text_ver.setEnabled(True)
        else:
            self.text_ver.setEnabled(False)
            self.text_ver.setText(self.old_version)


    # def check_i10_slot(self):
    #     try:
    #         if os.path.exists(self.config['file_path1']):
    #             self.load_file(self.config['file_path1'], self.text_filename1)
    #         if os.path.exists(self.config['file_path2']):
    #             self.load_file(self.config['file_path2'], self.text_filename2)
    #     except Exception as e:
    #         print(e)
    #         QMessageBox.information(self, '错误', '同步加载i10文件失败!', QMessageBox.Ok)

    # def get_update_MSG(self):
    #     while self.queue_program_update.qsize():
    #         state = self.queue_program_update.get()
    #         if state[0] == 0:
    #             if state[1] == 0:
    #                 self.echo_text(state[2][0], state[2][1])
    #         elif state[0] == 1:
    #             pass

    def get_e2prom_ver_time(self):
        self.signal_operat.emit(4, 3, [None])

    def update_IP(self, str):
        self.text_IP.setText(str)

    def get_e2prom_ver_time_response(self, ver, times):
        if ver:
            num3 = ver & 1023
            num2 = (ver >> 10) & 1023
            num1 = (ver >> 20) & 1023
            ver_num2 = [num1, num2, num3]
            ver_text2 = str(ver_num2[0]) + '.' + str(ver_num2[1]) + '.' + str(ver_num2[2])
            self.old_version = ver_text2
            self.text_ver.setText(ver_text2)
        if times:
            time_str = str(datetime.datetime.fromtimestamp(times))
            self.label_time.setText(time_str)

    def add_info_data(self):
        """ 获取记录 """
        self.text_IP.setText(self.config['IP'])
        self.text_PORT.setText(self.config['PORT'])
        self.text_filename1.setText(self.config['file_path1'])
        self.text_filename2.setText(self.config['file_path2'])
        if os.path.exists(self.config['file_path1']) and self.config['file_path1'] != '':
            self.load_file(self.config['file_path1'], self.text_filename1)
        if os.path.exists(self.config['file_path2']) and self.config['file_path2'] != '':
            self.load_file(self.config['file_path2'], self.text_filename2)
        self.check_filename1.setChecked(self.config['check1'])
        self.check_filename2.setChecked(self.config['check2'])
        # if 'check3' in self.config:
        #     self.check_i10.setChecked(self.config['check3'])

    def select_file(self, text_filename):
        if text_filename.index == 0:
            if self.config['file_path1']:
                # load_way = File_Process.get_record_path(self.config['file_path1'])
                load_way = self.config['file_path1']
            else:
                load_way = ''
        elif text_filename.index == 1:
            if self.config['file_path2']:
                # load_way = File_Process.get_record_path(self.config['file_path2'])
                load_way = self.config['file_path1']
            else:
                load_way = ''
        else:
            load_way = ''
        # print(self.config)
        # if self.config['file_path1']:
        #     load_way = File_Process.get_record_path(self.config['file_path1'])
        # else:
        #     load_way = ''
        file_name, file_type = QFileDialog.getOpenFileName(self, '打开文件', load_way, 'HWX文件(*.hex);;TXT文件(*.txt)')
        if file_name:
            self.load_file(file_name, text_filename)

    # 读取文件
    def load_file(self, file_path, text_filename):
        list_hex = []
        list_hex2 = []
        # 判断是否需要导入i10文件
        file_path_i10 = file_path.replace("hex", "i10", 1)
        # if self.check_i10.isChecked():
        #     if os.path.exists(file_path_i10):
        #         with open(file_path_i10, 'r', encoding='utf-8') as f:
        #             for line in f.readlines():
        #                 list_hex.append(line.lstrip(':').rstrip('\n'))
        #                 list_hex2.append(line)
        #             list_hex.pop()
        #             list_hex2.pop()

        if self.check_i10_needed(file_path):
            if self.check_i10_time(file_path, file_path_i10):
                with open(file_path_i10, 'r', encoding='utf-8') as f:
                    for line in f.readlines():
                        list_hex.append(line.lstrip(':').rstrip('\n'))
                        list_hex2.append(line)
                    list_hex.pop()
                    list_hex2.pop()
            else:
                QMessageBox.information(self, '提示', '根据选择的hex文件查出需要i10文件,\n请将i10文件放入同级目录后尝试重新读取,\n否则CLA的数学库函数可能失效!')

        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f.readlines():
                list_hex.append(line.lstrip(':').rstrip('\n'))
                list_hex2.append(line)

        if self.check_hex(list_hex2):
            text_filename.setText(file_path)
            if text_filename.index == 0:
                self.config['file_path1'] = file_path
            elif text_filename.index == 1:
                self.config['file_path2'] = file_path
            text_filename.list_send, text_filename.list_line = self.change_format(list_hex)
            text_filename.read_flag = True
            text_filename.check_flag.setChecked(True)
        else:
            text_filename.read_flag = False
            text_filename.check_flag.setChecked(False)
            QMessageBox.information(self, '提示', '选择的文件无效!\n请重新尝试!')

    def check_i10_needed(self, hex_file_path):
        """ 用于检查.hex文件中某一具体地址是否为具体数据"""
        real_addr = '00084004'
        real_data = 'FF112233445566FF'

        list_hex = []
        list_hex2 = []
        with open(hex_file_path, 'r', encoding='utf-8') as f:
            for line in f.readlines():
                list_hex.append(line.lstrip(':').rstrip('\n'))
                list_hex2.append(line)
        addr_high = ''
        for data in list_hex:
            if data[6:8] == '04':
                addr_high = data[8:12]
            elif data[6:8] == '00':
                if addr_high + data[2:6] == real_addr:
                    if len(data) > 24:
                        if data[8:24] == real_data:
                            return True
                        else:
                            return False
            else:
                pass

        return False

    def check_i10_time(self, hex_file_path, i10_file_path):
        if not os.path.exists(hex_file_path):
            return False
        if not os.path.exists(i10_file_path):
            return False
        last_modified_hex = datetime.datetime.fromtimestamp(os.path.getmtime(hex_file_path)).strftime("%Y-%m-%d %H:%M:%S")
        last_modified_i10 = datetime.datetime.fromtimestamp(os.path.getmtime(i10_file_path)).strftime("%Y-%m-%d %H:%M:%S")
        if last_modified_hex == last_modified_i10:
            return True
        else:
            return False

    def check_hex(self, list_hex):
        """ 校验读进来的文件数据 """
        list_data = []
        list_int = []
        for i in range(len(list_hex)):
            if list_hex[i][0] == ':':
                list_data.append(list_hex[i].lstrip(':').rstrip('\n'))
            else:
                print(i)
                return False
        for i in range(len(list_data)):
            if len(list_data[i]) % 2 == 1 or len(list_data[i]) != int(list_data[i][0:2], 16) * 2 + 10:

                print(len(list_data[i]) % 2 == 1 or len(list_data[i]), int(list_data[i][0:2], 16) * 2 + 10)
                print(i)
                return False
            else:
                sum = 0
                for j in range(0, len(list_data[i]) - 2, 2):
                    sum += int(list_data[i][j:j + 2], 16)
                sum = sum % 256
                sum = 256 - sum
                if sum == 256:
                    sum = 0
                if sum != int(list_data[i][-2:], 16):
                    print(sum, int(list_data[i][-2:], 16))
                    print(i)
                    return False
        return True

    def change_format(self, list_hex, line_num_max=20):
        """ 将数据转换成想要的长度 """
        list_send = []
        list_line = []
        line_num = 0
        adr_num = 0
        str = ''
        str_data = ''
        str_check = ''
        str_start = ''
        for i in range(len(list_hex)):
            if list_hex[i][6:8] == '00':
                if i == 0:
                    str_data = list_hex[i][8:-2]
                    if list_hex[i][0:2] == '20':
                        str_check = '00' + list_hex[i][-2:]
                    else:
                        str_check = list_hex[i][0:2] + list_hex[i][-2:]
                    line_num = 1
                    adr_num = int(int(list_hex[i][0:2], 16) / 2)
                    str_start = list_hex[i][2:6]

                elif list_hex[i - 1][6:8] != '00':
                    str_data = list_hex[i][8:-2]
                    if list_hex[i][0:2] == '20':
                        str_check = '00' + list_hex[i][-2:]
                    else:
                        str_check = list_hex[i][0:2] + list_hex[i][-2:]
                    line_num = 1
                    adr_num = int(int(list_hex[i][0:2], 16) / 2)
                    str_start = list_hex[i][2:6]

                elif (list_hex[i - 1][6:8] == '00' and int(list_hex[i - 1][2:6], 16) + int(
                        int(list_hex[i - 1][0:2], 16) / 2) != int(list_hex[i][2:6], 16)) or line_num == line_num_max:
                    str = 'FFFFFFFF0000' + str_start + ''.join(f"{adr_num:04x}") + ''.join(f"{line_num:04x}")
                    str += str_data
                    str += str_check
                    list_send.append(str)
                    list_line.append(line_num)

                    str_data = list_hex[i][8:-2]
                    if list_hex[i][0:2] == '20':
                        str_check = '00' + list_hex[i][-2:]
                    else:
                        str_check = list_hex[i][0:2] + list_hex[i][-2:]
                    line_num = 1
                    adr_num = int(int(list_hex[i][0:2], 16) / 2)
                    str_start = list_hex[i][2:6]

                else:
                    str_data += list_hex[i][8:-2]
                    if list_hex[i][0:2] == '20':
                        str_check += '00' + list_hex[i][-2:]
                    else:
                        str_check += list_hex[i][0:2] + list_hex[i][-2:]
                    line_num += 1
                    adr_num += int(int(list_hex[i][0:2], 16) / 2)
            elif list_hex[i][6:8] == '04':
                if i != 0:
                    str = 'FFFFFFFF0000' + str_start + ''.join(f"{adr_num:04x}") + ''.join(f"{line_num:04x}")
                    str += str_data
                    str += str_check
                    list_send.append(str)
                    list_line.append(line_num)
                else:
                    pass

                str = 'FFFFFFFF0004000000010001' + list_hex[i][8:12] + list_hex[i][0:2] + list_hex[i][12:14]
                list_send.append(str)
                list_line.append(1)

            elif list_hex[i][6:8] == '01':
                str = 'FFFFFFFF0000' + str_start + ''.join(f"{adr_num:04x}") + ''.join(f"{line_num:04x}")
                str += str_data
                str += str_check
                list_send.append(str)
                list_line.append(line_num)
                str = 'FFFFFFFF0001000000010001000000' + list_hex[i][8:10]
                list_send.append(str)
                list_line.append(1)
        return list_send, list_line

    def update_tcp(self):
        """ 做更新前的处理和判断 """
        if self.button_action.isChecked():
            ver_text = self.text_ver.text()
            if ver_text:
                if not re.match(r'^\d+\.\d+\.\d+$', ver_text):
                    QMessageBox.information(self, '提示', '版本格式有误\n请重新输入')
                    self.button_action.setChecked(False)
                    return
            if self.text_filename1.read_flag or self.text_filename2.read_flag:
                response_bit = ''
                self.list_send = []
                self.list_line = []
                if self.text_filename2.check_flag.isChecked():
                    if not self.text_filename2.read_flag:
                        QMessageBox.information(self, '提示', '请尝试修改CPU2路径过后再试!')
                        return
                if self.text_filename2.read_flag and self.text_filename2.check_flag.isChecked():
                    response_bit += '1'
                    self.list_send = self.text_filename2.list_send
                    self.list_line = self.text_filename2.list_line
                else:
                    response_bit += '0'
                if self.text_filename1.check_flag.isChecked():
                    if not self.text_filename1.read_flag:
                        QMessageBox.information(self, '提示', '请尝试修改CPU1路径过后再试!')
                        return
                if self.text_filename1.read_flag and self.text_filename1.check_flag.isChecked():
                    response_bit += '1'
                    self.list_send = self.text_filename1.list_send + self.list_send
                    self.list_line = self.text_filename1.list_line + self.list_line
                else:
                    response_bit += '0'
                self.response_hex = '000' + (hex(int(response_bit, 2)))[2]
                self.cpu_select = [self.text_filename1.check_flag.isChecked(),
                                   self.text_filename2.check_flag.isChecked()]

                # 获取信息
                ver_text = self.text_ver.text()
                if ver_text:
                    if not re.match(r'^\d+\.\d+\.\d+$', ver_text):
                        return
                    list_ver = ver_text.split('.')
                    list_ver = [int(num) for num in list_ver]
                    ver_num = list_ver[0] << 20 | list_ver[1] << 10 | list_ver[2]
                    # print(1, ver_num)
                    ver_num_hex = hex(ver_num)[2:].zfill(8)
                else:
                    ver_num = 1049601
                    ver_num_hex = hex(ver_num)[2:].zfill(8)

                time_num = int(time.time())
                time_num_hex = hex(time_num)[2:].zfill(8)
                self.information = 'FFFFFFFF0005000000040001' + ver_num_hex + time_num_hex + 'FFFF'
                # print(self.information)

                sum = 0
                for a in self.list_send:
                    sum += len(a)
                # for a in self.list_line:
                #     sum += a
                # print('sum:', sum)
                self.progress_bar.setRange(0, sum)
                self.finish_sum = 0
                self.progress_bar.setValue(self.finish_sum)
                self.signal_operat.emit(4, 1, [None])
                # self.thread = Thread(target=self.thread_tcp)
                # self.thread.start()
                # self.widget_disable()
                # self.button_action.setText('停止')

            elif not (self.text_filename1.read_flag or self.text_filename2.read_flag):
                self.button_action.setChecked(False)
                QMessageBox.information(self, '提示', '请先选取文件再尝试!')
            else:
                print('不可知的意外!')
        else:
            self.thread_flag = False
            if self.get_update_MSG_timer:
                self.get_update_MSG_timer.stop()
            self.widget_enable()
            self.button_action.setText('开始')
            self.label_text.setText('停止了更新')
            self.finish_sum = 0
            self.progress_bar.setValue(self.finish_sum)


    @log_decorator
    def thread_start(self):
        # 判断更新时所需要的延时
        # if len(self.list_send) > 3200:
        #     self.delay_time = 0
        # elif len(self.list_send) > 1600:
        #     self.delay_time = 0.01
        # elif len(self.list_send) > 800:
        #     self.delay_time = 0.02
        # elif len(self.list_send) > 400:
        #     self.delay_time = 0.03
        # elif len(self.list_send) > 100:
        #     self.delay_time = 0.04
        # elif len(self.list_send) > 50:
        #     self.delay_time = 0.05
        # elif len(self.list_send) > 0:
        #     self.delay_time = 0.1

        # self.thread = Thread(target=self.thread_tcp)
        # self.thread.start()
        self.widget_disable()
        self.button_action.setText('停止')

        self.get_update_MSG_timer = QtCore.QTimer()  # 保存config的定时器
        self.get_update_MSG_timer.timeout.connect(self.get_update_MSG)
        self.update_step = 0
        self.conn_err_count = 0
        self.get_update_MSG_timer.start(10)
        # print(len(self.list_send))

    def get_update_MSG(self):
        # print(self.update_step)
        if self.update_step == 0:
            # self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # self.client.settimeout(0.5)
            # self.count = -1
            # str_tip = '正在等待连接······'
            # self.send_signal(str_tip, self.count)
            # self.queue_program_update.put([0, 0, [str_tip, count]])
            self.count = -1
            self.check_err = 0
            self.write_err = 0
            self.succeed_count = -1
            self.update_step += 1
            str_tip = '初始化成功 ······'
            self.send_signal(str_tip, self.count)
            self.get_update_MSG_timer.start(1000)

        elif self.update_step == 1:
            try:
                # time.sleep(0.2)
                self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.client.settimeout(0.1)
                self.client.connect((self.text_IP.text(), int(self.text_PORT.text())))
                self.client.settimeout(2)
                # time.sleep(0.1)
                self.client.send(bytearray.fromhex('FFFFFFFF00FF00000002000112341234' + self.response_hex))
                # print('FFFFFFFF00FF00000002000112341234' + self.response_hex)
                str_tip = '连接成功，等待发送 ······'
                self.send_signal(str_tip, self.count)
                # self.queue_program_update.put([0, 0, [str_tip, count]])
                self.update_step += 1
                self.get_update_MSG_timer.start(30)
                self.send_signal3(False)
            except Exception as e:
                print(e)
                # self.get_update_MSG_timer.start(1000)
                self.conn_err_count += 1
                if self.conn_err_count == 1000:
                    self.update_step = 4
        elif self.update_step == 2:
            result = None
            try:
                result = self.client.recv(1024).hex().upper()
            except Exception as e:
                # print(e)
                self.send_signal3(True)
                self.send_signal4()
                str_tip = '请重试 ······'
                self.send_signal(str_tip, self.count)
                self.update_step += 2
            if result:
                # print(result)
                if 'FFFFFFFF00FF000000020001FFFFFFFF' in result:
                    # print(self.information)
                    self.client.send(bytearray.fromhex(self.information))
                    str_tip = '版本信息传输成功······'
                    self.send_signal(str_tip, self.count)
                    # self.count = -1
                    # self.succeed_count = -1
                elif 'FFFFFFFF00FF00000002000100000000' in result:
                    # my_logger.warning('烧写程序时验证密码失败!')
                    self.queue_logging.put([1, 2, '烧写程序时验证密码失败!'])
                    self.send_signal3(True)
                    print('密码认证失败')
                elif 'FFFFFFFF0003' in result:
                    self.count += 1
                    self.succeed_count += 1
                    self.client.send(bytearray.fromhex(self.list_send[self.count]))
                    if self.count == len(self.list_send) - 1:
                        self.succeed_count += 1
                        str_tip = '远程升级完成---写入成功: ' + str(self.succeed_count) + '次  校验失败: ' + str(
                            self.check_err) + '次   写入失败: ' + str(self.write_err) + '次'
                        self.send_signal(str_tip, self.count)
                        # print(self.count)
                        # self.queue_program_update.put([0, 0, [str_tip, count]])
                        print('完成')
                        # time.sleep(3)
                        # self.button_port.setEnabled(True)
                        self.send_signal2()
                        self.send_signal3(True)
                        self.update_step += 1
                        return
                    str_tip = '正在执行远程升级---写入成功: ' + str(self.succeed_count) + '次   校验失败: ' + str(
                        self.check_err) + '次   写入失败: ' + str(self.write_err) + '次'
                    # print(self.count)
                    self.send_signal(str_tip, self.count)
                    # self.queue_program_update.put([0, 0, [str_tip, count]])
                elif 'FFFFFFFF0004' in result:
                    self.check_err += 1
                    self.client.send(bytearray.fromhex(self.list_send[self.count]))
                    str_tip = '正在执行远程升级---写入成功: ' + str(self.succeed_count) + '次   校验失败: ' + str(
                        self.check_err) + '次   写入失败: ' + str(self.write_err) + '次'
                    self.send_signal(str_tip)
                    # self.queue_program_update.put([0, 0, [str_tip, count]])
                elif 'FFFFFFFF0005' in result:
                    self.write_err += 1
                    self.client.send(bytearray.fromhex('FFFFFFFF'))
                    str_tip = '正在执行远程升级---写入成功: ' + str(self.succeed_count) + '次   校验失败: ' + str(
                        self.check_err) + '次   写入失败: ' + str(self.write_err) + '次'
                    self.send_signal3(True)
                    self.send_signal(str_tip)
                    # self.queue_program_update.put([0, 0, [str_tip, count]])
                elif 'FFFFFFFF0006' in result:
                    str_tip = '执行擦除命令时发生意外!'
                    self.send_signal3(True)
                    self.send_signal(str_tip)

        elif self.update_step == 3:
            self.get_update_MSG_timer.stop()
        elif self.update_step == 4:
            self.get_update_MSG_timer.stop()

    # def thread_tcp(self):
    #     """ 网口处理的线程 """
    #     self.thread_flag = True
    #     self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #     count = -1
    #     str_tip = '正在等待连接······'
    #     self.send_signal(str_tip, count)
    #     # self.queue_program_update.put([0, 0, [str_tip, count]])
    #     check_err = 0
    #     write_err = 0
    #     succeed_count = 0
    #     # while self.thread_flag:
    #     #     print(self.text_IP.text())
    #     #     p = os.popen("ping " + self.text_IP.text() + " -n 2")
    #     #     line = p.read()
    #     #     if "请求超时" in line or "无法访问目标主机" in line or "找不到主机" in line or '传输失败' in line:
    #     #         pass
    #     #     else:
    #     #         break
    #     while self.thread_flag:
    #         try:
    #             # time.sleep(0.2)
    #             self.client.connect((self.text_IP.text(), int(self.text_PORT.text())))
    #             time.sleep(0.1)
    #             self.client.send(bytearray.fromhex('FFFFFFFF00FF00000002000112341234' + self.response_hex))
    #             # print('FFFFFFFF00FF00000002000112341234' + self.response_hex)
    #             str_tip = '测试成功等待连接······'
    #             self.send_signal(str_tip, count)
    #             # self.queue_program_update.put([0, 0, [str_tip, count]])
    #             break
    #         except Exception as e:
    #             pass
    #     # result = client.recv(1024)
    #     # print(result.hex().upper())
    #     self.send_signal3(False)
    #
    #
    #     while self.thread_flag:
    #         start_time = time.time()
    #         # if self.delay_time:
    #         #     time.sleep(self.delay_time)        # 由于更新速度太快暂时加延时以抵抗速度太快造成的影响，后期数据量增大可以去掉该延时
    #         try:
    #             result = self.client.recv(1024).hex().upper()
    #         except Exception as e:
    #             self.send_signal3(True)
    #             self.send_signal4()
    #             break
    #         if result:
    #             if 'FFFFFFFF00FF000000020001FFFFFFFF' in result:
    #                 self.client.send(bytearray.fromhex(self.information))
    #                 str_tip = '版本信息传输成功······'
    #                 self.send_signal(str_tip, count)
    #                 # self.queue_program_update.put([0, 0, [str_tip, count]])
    #
    #                 # count += 1
    #                 # succeed_count += 1
    #                 # self.client.send(bytearray.fromhex(self.list_send[count]))
    #                 # str_tip = '连接成功等待传输······'
    #                 # self.send_signal(str_tip, count)
    #             elif 'FFFFFFFF00FF00000002000100000000' in result:
    #                 # my_logger.warning('烧写程序时验证密码失败!')
    #                 self.queue_logging.put([1, 2, '烧写程序时验证密码失败!'])
    #                 self.send_signal3(True)
    #                 print('密码认证失败')
    #             elif 'FFFFFFFF0003' in result:
    #                 count += 1
    #                 succeed_count += 1
    #                 self.client.send(bytearray.fromhex(self.list_send[count]))
    #                 if count == len(self.list_send) - 1:
    #                     succeed_count += 1
    #                     str_tip = '远程升级完成---写入成功: ' + str(succeed_count) + '次  校验失败: ' + str(
    #                         check_err) + '次   写入失败: ' + str(write_err) + '次'
    #                     self.send_signal(str_tip, count)
    #                     # self.queue_program_update.put([0, 0, [str_tip, count]])
    #                     print('完成')
    #                     # time.sleep(3)
    #                     # self.button_port.setEnabled(True)
    #                     self.send_signal2()
    #                     self.send_signal3(True)
    #
    #                     break
    #                 str_tip = '正在执行远程升级---写入成功: ' + str(succeed_count) + '次   校验失败: ' + str(
    #                     check_err) + '次   写入失败: ' + str(write_err) + '次'
    #                 self.send_signal(str_tip, count)
    #                 print(count, time.time())
    #                 # self.queue_program_update.put([0, 0, [str_tip, count]])
    #             elif 'FFFFFFFF0004' in result:
    #                 check_err += 1
    #                 self.client.send(bytearray.fromhex(self.list_send[count]))
    #                 str_tip = '正在执行远程升级---写入成功: ' + str(succeed_count) + '次   校验失败: ' + str(
    #                     check_err) + '次   写入失败: ' + str(write_err) + '次'
    #                 self.send_signal(str_tip)
    #                 # self.queue_program_update.put([0, 0, [str_tip, count]])
    #             elif 'FFFFFFFF0005' in result:
    #                 write_err += 1
    #                 self.client.send(bytearray.fromhex('FFFFFFFF'))
    #                 str_tip = '正在执行远程升级---写入成功: ' + str(succeed_count) + '次   校验失败: ' + str(
    #                     check_err) + '次   写入失败: ' + str(write_err) + '次'
    #                 self.send_signal3(True)
    #                 self.send_signal(str_tip)
    #                 # self.queue_program_update.put([0, 0, [str_tip, count]])
    #             elif 'FFFFFFFF0006' in result:
    #                 str_tip = '执行擦除命令时发生意外!'
    #                 self.send_signal3(True)
    #                 self.send_signal(str_tip)
    #                 # self.queue_program_update.put([0, 0, [str_tip, count]])
    #             if self.delay_time:
    #                 time.sleep(self.delay_time)        # 由于更新速度太快暂时加延时以抵抗速度太快造成的影响，后期数据量增大可以去掉该延时
    #         exc_time = time.time()
    #         if exc_time < 0.05:
    #             time.sleep(0.05 - exc_time)
    #         # new_time = time.time()
    #         # print(count, new_time - self.start_time)
    #         # self.start_time = new_time

    # 显示数字
    def echo_text(self, strs, ints):
        # print(ints, '--', time.time())
        # print(ints)
        self.label_text.setText(strs)
        if ints >= 0:
            # self.finish_sum += self.list_line[ints]
            self.finish_sum += len(self.list_send[ints])
            # print('all:', self.finish_sum)
            self.progress_bar.setValue(self.finish_sum)
            # new_time = time.time()
            # print(ints, new_time - self.start_time)
            # self.start_time = new_time

    # 发送信号
    def send_signal(self, strs, ints=-1):
        self.signal_echo.echo_signal.emit(strs, ints)

    def send_signal2(self):
        self.signal_done.done_signal.emit(1)

    def send_signal3(self, flag):
        if flag:
            self.signal_done.done_signal.emit(2)
        else:
            self.signal_done.done_signal.emit(3)

    def send_signal4(self):
        self.signal_done.done_signal.emit(4)

    # 完成事件
    @log_decorator
    def update_done(self, ints):
        if ints == 1:
            self.thread_flag = False
            # self.finish_sum = 0
            # self.progress_bar.setValue(self.finish_sum)
            self.widget_enable()
            self.client.close()
            # self.text_filename1.setText('')
            # self.text_filename2.setText('')
            # self.check_filename1.setChecked(False)
            # self.check_filename2.setChecked(False)
            # self.text_filename1.read_flag = False
            # self.text_filename2.read_flag = False
            self.button_action.setText('开始')
            # 给主程序发送完成信号
            self.close()
            time.sleep(3)
            self.signal_operat.emit(4, 2, [None])
            # self.close()
        elif ints == 2:
            self.button_action.setEnabled(True)
        elif ints == 3:
            self.button_action.setEnabled(False)
        elif ints == 4:
            QMessageBox.information(self, '提示', '在传输过程中出现断开连接\n请重试!', QMessageBox.Yes)

    def show_MSG(self, msg):
        if self.button_action.isChecked():
            self.button_action.setChecked(False)
        QMessageBox.information(self, '提示', msg, QMessageBox.Yes)

    def request_update(self):
        self.countdown = 5
        self.msg_box = QMessageBox()
        self.msg_box.setWindowTitle('确认({}s后自动关闭)'.format(str(self.countdown)))
        self.msg_box.setText('当前有program程序\n版本:' + self.old_version + '\n是否继续升级')
        self.msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        self.count_timer.start(1000)
        replay = self.msg_box.exec()
        # replay = QMessageBox.question(self, '确认', '当前有program程序\n版本:' + self.old_version + '\n 是否继续升级', QMessageBox.Yes | QMessageBox.No)
        if replay == QMessageBox.Yes:
            self.signal_operat.emit(4, 4, [True])
        else:
            self.signal_operat.emit(4, 4, [False])
            self.button_action.setChecked(False)

    def count_timer_slot(self):
        self.countdown -= 1
        self.msg_box.setWindowTitle('确认({}s后自动关闭)'.format(str(self.countdown)))
        if self.countdown == 0:
            self.msg_box.close()
            self.count_timer.stop()

    def widget_enable(self):
        """ 烧写时禁用控件 """
        self.text_IP.setEnabled(True)
        self.text_PORT.setEnabled(True)
        self.button_loadfile1.setEnabled(True)
        self.button_loadfile2.setEnabled(True)
        self.check_filename1.setEnabled(True)
        self.check_filename2.setEnabled(True)
        self.button_action.setChecked(False)

    # 禁用控件
    def widget_disable(self):
        """ 烧写完成打开控件 """
        self.text_IP.setEnabled(False)
        self.text_PORT.setEnabled(False)
        self.button_loadfile1.setEnabled(False)
        self.button_loadfile2.setEnabled(False)
        self.check_filename1.setEnabled(False)
        self.check_filename2.setEnabled(False)

    def get_config(self):
        self.config = {
            'file_path1': self.text_filename1.text(),
            'file_path2': self.text_filename2.text(),
            'IP': self.text_IP.text(),
            'PORT': self.text_PORT.text(),
            'check1': self.check_filename1.isChecked(),
            'check2': self.check_filename2.isChecked(),
            # 'check3': self.check_i10.isChecked()
        }

    def closeEvent(self, event:PySide6.QtGui.QCloseEvent) -> None:
        """ 重写窗口的关闭事件 """
        if self.button_action.text() == '开始':
            self.get_config()
            # self.get_update_MSG_timer.stop()
            self.thread_flag = False
            super().closeEvent(event)
            self.signal_operat.emit(4, 0, [self.config])
        else:
            qm = QMessageBox.warning(self, "警告", "强行中断升级可能会引发意外!\n是否确认停止并退出",
                                     QMessageBox.Yes | QMessageBox.No)
            if qm == QMessageBox.Yes:
                self.get_config()
                # self.get_update_MSG_timer.stop()
                self.thread_flag = False
                super().closeEvent(event)
                self.signal_operat.emit(4, 0, [self.config])
            else:
                event.ignore()



class Singnal_Echo(QObject):
    echo_signal = Signal(str, int)

class Singnal_Done(QObject):
    done_signal = Signal(int)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWin = Program_Update()  # scaleRate)
    myWin.show()
    sys.exit(app.exec())
